

namespace Stee.CAP8.MessageBus.Kafka.Utility
{
    using System;
    using Stee.CAP8.MessageBus.Interfaces.Models;
    using Stee.CAP8.MessageBus.Kafka.Configurations;

    public static class ValidateHelper
    {
        /// <summary>
        /// Validate topic name
        /// </summary>
        /// <param name="topicName">Topic name</param>
        /// <returns>Return TRUE if valid else FALSE</returns>
        public static bool ValidateTopicName(TopicName topicName)
        {
            var topic = topicName?.Name.Trim();

            if (topicName == null)
            {
                throw new ArgumentNullException($"Topic name is null: {nameof(topicName)}");
            }
            else if (string.IsNullOrEmpty(topic))
            {
                throw new ArgumentNullException($"Null or empty message topic encountered: {nameof(topicName)}");
            }

            return true;
        }

        /// <summary>
        /// Validate topic configuration
        /// </summary>
        /// <param name="topicConfiguration">Topic configuration</param>
        /// <returns>Return TRUE if valid else FALSE</returns>
        public static bool ValidateTopicConfiguration(TopicConfiguration topicConfiguration)
        {
            var topic = topicConfiguration?.Name?.Trim();

            if (topicConfiguration == null)
            {
                throw new ArgumentNullException($"Null topic configuration encountered: {nameof(topicConfiguration)}");
            }
            else if (string.IsNullOrEmpty(topic))
            {
                throw new ArgumentNullException($"Null or empty message topic encountered: {nameof(topicConfiguration.Name)}");
            }
            else if (topicConfiguration.NumOfPartitions < 1)
            {
                throw new ArgumentException($"Topic partition count cannot be less than 1: {topicConfiguration.NumOfPartitions}");
            }
            else if (topicConfiguration.ReplicationFactor < 1)
            {
                throw new ArgumentException($"Topic replication factor cannot be less than 1: {topicConfiguration.ReplicationFactor}");
            }

            return true;
        }

        /// <summary>
        /// Validate generic message
        /// </summary>
        /// <param name="genericMsg">Generic message</param>
        /// <returns>Return TRUE if valid else FALSE</returns>
        public static bool ValidateGeneric(GenericMessage genericMsg)
        {
            if (genericMsg == null)
            {
                throw new ArgumentNullException($"Null generic message encountered: {nameof(genericMsg)}");
            }
            else if (string.IsNullOrEmpty(genericMsg.MessageDataType.Trim()))
            {
                throw new ArgumentNullException($"Null generic message type encountered: {nameof(genericMsg.MessageDataType)}");
            }
            else if (genericMsg.Data == null)
            {
                throw new ArgumentNullException($"Null generic data encountered: {nameof(genericMsg.Data)}");
            }

            return true;
        }

        /// <summary>
        /// Validate command message
        /// </summary>
        /// <param name="commandMsg">Command message</param>
        /// <returns>Return TRUE if valid else FALSE</returns>
        public static bool ValidateCommand(CommandMessage commandMsg)
        {
            if (commandMsg == null)
            {
                throw new ArgumentNullException($"Null command message encountered: {nameof(commandMsg)}");
            }
            else if (string.IsNullOrEmpty(commandMsg.Action))
            {
                throw new ArgumentNullException($"Null command action encountered: {nameof(commandMsg.Action)}");
            }
            else if (commandMsg.Data == null)
            {
                throw new ArgumentNullException($"Null command data encountered: {nameof(commandMsg.Data)}");
            }

            return true;
        }

        /// <summary>
        /// Validate event message
        /// </summary>
        /// <param name="commandMsg">Event message</param>
        /// <returns>Return TRUE if valid else FALSE</returns>
        public static bool ValidateEvent(EventMessage eventMsg)
        {
            if (eventMsg == null)
            {
                throw new ArgumentNullException($"Null event message encountered: {nameof(eventMsg)}");
            }
            else if (string.IsNullOrEmpty(eventMsg.Action))
            {
                throw new ArgumentNullException($"Null event action encountered: {nameof(eventMsg.Action)}");
            }
            else if (eventMsg.Data == null)
            {
                throw new ArgumentNullException($"Null event data encountered: {nameof(eventMsg.Data)}");
            }

            return true;
        }


        /// <summary>
        /// Compare 2 strings' equality
        /// </summary>
        /// <param name="str1">String 1</param>
        /// <param name="str2">String 2</param>
        /// <returns>Return TRUE if both string are equal else FALSE</returns>
        public static bool StringEquals(string str1, string str2)
        {
            var s1 = CheckString(str1, false);
            var s2 = CheckString(str2, false);
            var isEqual = !string.IsNullOrEmpty(s1) && !string.IsNullOrEmpty(s2);
            isEqual &= string.Equals(s1, s2, StringComparison.InvariantCultureIgnoreCase);

            return isEqual;
        }

        /// <summary>
        /// Checks string value is NULL, empty and for trailing whitespace
        /// </summary>
        /// <param name="value">String value to check</param>
        /// <param name="isThrowOnNullOrEmpty">Throw null exception on NULL string<param>
        /// <paramref name="excpMsg">Exception message to throw<param>
        /// <returns>Return new string without trailing whitespace</returns>
        public static string CheckString(string value, bool isThrowOnNullOrEmpty = true, string excpMsg = "Null string encountered.")
        {
            var str = value?.Trim();

            if (isThrowOnNullOrEmpty && string.IsNullOrEmpty(str))
            {
                throw new ArgumentNullException(excpMsg);
            }

            return str;
        }
    }
}
